#!/bin/python3

from optparse import OptionParser
import requests
import re
import time
import sys
import os
import asyncio

class IP138(object):
    def __init__(self,op):
        self.url = op.url
        self.history = op.history
        self.noping = op.noping
        self.pingnum = op.pingnum
        self.session = requests.session()
        self.headers = {"User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:79.0) Gecko/20100101 Firefox/79.0"}
        self.session.headers = self.headers
        self.root_url = "https://site.ip138.com/{ip}/".format(ip = self.url)
        self.urlwrite1 = "https://site.ip138.com/domain/write.do?input={ip}&token={token}"
        self.urlread = "https://site.ip138.com/domain/read.do?domain={ip}&time={time}"
        self.urlwrite2 = "https://site.ip138.com/domain/write.do?type=domain&input={ip}&token={token}"
    
    def get_token1(self):
        try :
            r = self.session.get(self.root_url)
            r.raise_for_status()
            a = re.findall("var _TOKEN = '(.*?)';",r.text)[0]
            txt_list = re.findall("(?<=target=\"_blank\">)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?=</a>)",r.text)
            return a,txt_list
        except:
            return 0

    def send(self,token):#fayigekongbao
        try :
            r = self.session.get(self.urlwrite1.format(ip = self.url,token = token))
            r.raise_for_status()
            return 1
        except :
            return 0
    def get_read(self):
        try:
            timestr = str(time.time()).replace('.','')[0:13]
            r = self.session.get(self.urlread.format(ip=self.url,time = timestr))
            r.raise_for_status()
            return r.json()
        except:
            return 0

    def get_write2(self,token):
        try:
            r = self.session.get(self.urlwrite2.format(ip = self.urlwrite2,token = token))
            r.raise_for_status()
            return 1
        except:
            return 0

    async def packet(self,ip):
        a = await asyncio.create_subprocess_shell("ping -c {num} {ip}".format(ip = ip, num = self.pingnum),
                                                    stdout=asyncio.subprocess.PIPE,
                                                    stderr=asyncio.subprocess.PIPE
                                                        )
        stdout,__stderr = await a.communicate()
        stdout = stdout.decode('utf-8')
        # c =  re.findall("received, (.*?) packet loss,",stdout)[0]#丢包率
        c = re.findall("已接收.*?个包, (.*?) packet loss, time \d+ms",stdout)[0]
# '''
# packet loss, time 9033ms
# rtt min/avg/max/mdev = 145.546/171.560/199.640/19.594 ms
# '''
        d = stdout.split('\n')[-3].split(' ')[-1]
        print("{}\t{}#{}个包丢包率:{},时间:{}".format(ip,self.url,self.pingnum,c,d))

    async def mange(self):
        token1,txt = self.get_token1()
        #txt是历史ip列表
        if self.history:
            for i in txt:
                print("#{}\t{}".format(i,self.url))
        self.send(token1)
        a = self.get_read()
        # print(a)
        print("#已经从服务器获取数据集")
        try:
            ip_list = [i['ip'] for i in a['data']]
            # print(ip_list)
            if self.noping :
                for i in ip_list:
                    print(i,'\t',self.url)
            else:
                task = [asyncio.ensure_future(self.packet(i)) for i in ip_list]
                await asyncio.gather(*task)
        except:
            print("域名异常,或程序异常")
        token2 = a['msg']
        self.get_write2(token2)

    def main(self):
        loop = asyncio.get_event_loop()
        loop.run_until_complete(self.mange())

if __name__ == "__main__" :
    option = OptionParser()
    option.add_option('-n','--num',action = 'store',type=int,dest = 'pingnum',default = 4, help = "这里是使用ping发送包的数量")
    option.add_option('-u','--url',action = 'store',type=str,dest = 'url', help = "这里是要检查的url")
    option.add_option('--noping',action = 'store_true',dest = 'noping', help = "这个参数存在就不发送ping包")
    option.add_option('--history',action = 'store_true',dest = 'history', help = "这个参数存在就检查历史ip")
    
    op = option.parse_args(sys.argv)[0]
    IP138(op).main()

#author=江户川_柯北
#version=0.5
#last change time=2021年3月12日10：41
#搞懂一丢丢异步，开始操作